﻿using MetaProperties.Core;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MetaProperties.Framework;
using System.ComponentModel;
using System.Collections.Generic;

namespace MetaProperties.Core.Tests
{
    using System;
    using System.Linq;


    /// <summary>
    ///This is a test class for MetaPropertyHostHelperTest and is intended
    ///to contain all MetaPropertyHostHelperTest Unit Tests
    ///</summary>
    [TestClass()]
    public class MetaPropertyHostHelperTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        private class TestHost : MetaPropertyHost
        {
            /// <summary>
            /// Observable Data field.
            /// </summary>
            private readonly Observable<int> notifyingData = new Observable<int>();

            /// <summary>
            /// Gets the Data.
            /// </summary>
            public int Data
            {
                get { return this.notifyingData.Value; }
                private set { this.notifyingData.Value = value; }
            }

            /// <summary>
            /// Gets the MetaProperty for the Data property.
            /// </summary>
            public IMetaProperty<int> DataProperty
            {
                get { return this.notifyingData.MetaProperty; }
            }
        }

        /// <summary>
        ///A test for MetaProperties
        ///</summary>
        [TestMethod()]
        public void MetaPropertiesTest()
        {
            IMetaPropertyHost host = new TestHost();
            MetaPropertyHostHelper target = new MetaPropertyHostHelper(host);
         
            Assert.IsNotNull(target.MetaProperties);
            Assert.AreEqual(0, target.MetaProperties.Count());
        }

        /// <summary>
        ///A test for OnPropertyChanged
        ///</summary>
        [TestMethod()]
        public void OnPropertyChangedTest()
        {
            IMetaPropertyHost host = new TestHost();
            MetaPropertyHostHelper target = new MetaPropertyHostHelper(host);


            string propertyName = "Test";
            bool eventCalled = false;

            target.PropertyChanged += (s, e) =>
                {
                    eventCalled = true;
                    Assert.AreEqual(host, s);
                    Assert.AreEqual(propertyName, e.PropertyName);
                };

            target.OnPropertyChanged(propertyName);

            Assert.IsTrue(eventCalled);
        }

        /// <summary>
        ///A test for MetaProperty_PropertyChanged
        ///</summary>
        [TestMethod()]
        [DeploymentItem("MetaProperties.Core.dll")]
        public void MetaProperty_PropertyChangedTest()
        {
            TestHost host = new TestHost();
            MetaPropertyHostHelper hostHelper = new MetaPropertyHostHelper(host);
            PrivateObject param0 = new PrivateObject(hostHelper);
            MetaPropertyHostHelper_Accessor target = new MetaPropertyHostHelper_Accessor(param0);

            object sender = host.DataProperty;
            PropertyChangedEventArgs args = new PropertyChangedEventArgs(host.DataProperty.PropertyName);

            bool eventCalled = false;

            hostHelper.PropertyChanged += (s, e) =>
            {
                eventCalled = true;
                Assert.AreEqual(host, s);
                Assert.AreEqual(host.DataProperty.PropertyName, e.PropertyName);
            };
            
            target.MetaProperty_PropertyChanged(sender, args);

            Assert.IsTrue(eventCalled);
        }

        /// <summary>
        ///A test for InitializePublicMetaProperties
        ///</summary>
        [TestMethod()]
        public void InitializePublicMetaPropertiesTest()
        {
            TestHost host = new TestHost();
            MetaPropertyHostHelper target = new MetaPropertyHostHelper(host);

            Assert.AreEqual(0, target.MetaProperties.Count());

            target.InitializePublicMetaProperties();

            Assert.AreEqual(1, target.MetaProperties.Count());

            Assert.AreEqual(host.DataProperty, target.MetaProperties.First());
        }

        /// <summary>
        ///A test for GetMetaProperty
        ///</summary>
        [TestMethod()]
        public void GetMetaPropertyTest()
        {
            TestHost host = new TestHost();
            MetaPropertyHostHelper target = new MetaPropertyHostHelper(host);

            Assert.IsNull(target.GetMetaProperty("Data"));

            target.InitializePublicMetaProperties();

            Assert.AreEqual(host.DataProperty, target.GetMetaProperty("Data"));
            Assert.IsNull(target.GetMetaProperty("Test"));
        }

        /// <summary>
        ///A test for AttachToMetaProperty
        ///</summary>
        [TestMethod()]
        [DeploymentItem("MetaProperties.Core.dll")]
        public void AttachToMetaPropertyTest()
        {
            TestHost host = new TestHost();
            MetaPropertyHostHelper hostHelper = new MetaPropertyHostHelper(host);
            PrivateObject param0 = new PrivateObject(hostHelper);
            MetaPropertyHostHelper_Accessor target = new MetaPropertyHostHelper_Accessor(param0);

            IMetaProperty metaProperty = host.DataProperty;

            Assert.IsNull(hostHelper.GetMetaProperty("Data"));

            target.AttachToMetaProperty(metaProperty);

            Assert.AreEqual(host.DataProperty, target.GetMetaProperty("Data"));
        }

        /// <summary>
        ///A test for AttachToMetaProperty
        ///</summary>
        [TestMethod()]
        [DeploymentItem("MetaProperties.Core.dll")]
        [ExpectedException(typeof(InvalidOperationException))]
        public void AttachToMetaPropertyTwiceTest()
        {
            TestHost host = new TestHost();
            MetaPropertyHostHelper hostHelper = new MetaPropertyHostHelper(host);
            PrivateObject param0 = new PrivateObject(hostHelper);
            MetaPropertyHostHelper_Accessor target = new MetaPropertyHostHelper_Accessor(param0);

            IMetaProperty metaProperty = host.DataProperty;

            target.AttachToMetaProperty(metaProperty);
            target.AttachToMetaProperty(metaProperty);
        }

        /// <summary>
        ///A test for MetaPropertyHostHelper Constructor
        ///</summary>
        [TestMethod()]
        public void MetaPropertyHostHelperConstructorTest()
        {
            IMetaPropertyHost host = new TestHost();
            MetaPropertyHostHelper target = new MetaPropertyHostHelper(host);

            Assert.IsNotNull(target.MetaProperties);
            Assert.AreEqual(0, target.MetaProperties.Count());
        }
    }
}
